package controllers

import (
	"pegasus/datatypes"
	"pegasus/models"
	"pegasus/repositories"
	"pegasus/utils"
)

//Character 游戏角色管理
type Character struct {
	utils.ILogger
}

//CHSimpleCharacterDto 描述每个角色
type CHSimpleCharacterDto struct {
	ID   int64
	Name string
}

//CHAllDto 所有的角色状态
type CHAllDto struct {
	Characters []*CHSimpleCharacterDto
}

//All 得到所有的角色ID
func (ch *Character) All(si datatypes.SIContent, cr *repositories.CharacterRepo) *Response {
	if si.Logined() != nil {
		return NewResponseErr(ErrorGeneric, "角色必须退出")
	}
	beans, err := cr.GetAll(si.User())
	if err != nil {
		return NewResponseErr(ErrorGeneric, err.Error())
	}
	rsp := &CHAllDto{Characters: make([]*CHSimpleCharacterDto, len(beans))}
	for i, v := range beans {
		rsp.Characters[i] = &CHSimpleCharacterDto{ID: v.ID, Name: v.Name}
	}
	return NewResponseSucc(rsp)
}

//CHCreateBM 人物创建
type CHCreateBM struct {
	Name string
}

//Create 创建一个角色
func (ch *Character) Create(si datatypes.SIContent, bm *CHCreateBM, cr *repositories.CharacterRepo) *Response {
	if bm.Name == "" {
		return NewResponseErr(ErrorGeneric, "角色名错误")
	}
	id, err := cr.Create(si.User(), bm.Name)
	if err != nil {
		return NewResponseErr(ErrorGeneric, err.Error())
	}
	ch.Infof("%d:创建人物 %d", si.User(), id)
	return NewResponseSucc(nil)
}

//CHSwitchBM 人物切换
type CHSwitchBM struct {
	CharacterID int64
}

//Switch 角色登录 每个用户只能登录1个角色
func (ch *Character) Switch(si datatypes.SIContent, bm *CHSwitchBM, cr *repositories.CharacterRepo, log *repositories.LogRepo) *Response {
	if bm.CharacterID < 0 || cr.CheckValid(si.User(), bm.CharacterID) != nil {
		return NewResponseErr(ErrorGeneric, "角色ID错误")
	}
	sc := datatypes.NewSICharacter(bm.CharacterID, si.User())
	si.Switch(sc)
	log.AddCharacter(bm.CharacterID)
	return NewResponseSucc(nil)
}

//Quit 角色登出
func (ch *Character) Quit(si datatypes.SIContent) *Response {
	//不管当前有没有人物登录都返回成功
	if sc := si.Logined(); sc != nil {
		si.Switch(nil)
	}
	return NewResponseSucc(nil)
}

//CHDetailedDto 用户详细信息
type CHDetailedDto struct {
	ID              int64
	Gold            int64
	Coin            int64
	PeriodUser      models.CharacterPeriodType
	TodayPeriodGift bool //PeriodUser == nomal时 field无效
	TotalSignIn     int
	TodaySignInGift bool
}

//GetDetailedInfo 得到已登录人物详细信息
func (ch *Character) GetDetailedInfo(sc datatypes.SICharacter, cr *repositories.CharacterRepo) *Response {
	bean, err := cr.GetDetailed(sc.ID())
	if err != nil {
		return NewResponseErr(ErrorGeneric, err.Error())
	}
	rsp := &CHDetailedDto{
		ID:              bean.ID,
		Gold:            bean.Gold,
		Coin:            bean.Coin,
		PeriodUser:      bean.PeriodType,
		TodayPeriodGift: false,
		TotalSignIn:     bean.TotalSignIn,
		TodaySignInGift: false,
	}
	if bean.PeriodSignInTime != nil {
		rsp.TodayPeriodGift = bean.PeriodSignInTime.After(utils.GetTodayZero()) //PeriodUser == nomal时 field无效
	}
	if bean.SignInTime != nil {
		rsp.TodaySignInGift = bean.SignInTime.After(utils.GetTodayZero())
	}

	return NewResponseSucc(rsp)
}

//SignIn 签到领礼物
func (ch *Character) SignIn(sc datatypes.SICharacter, cr *repositories.CharacterRepo) *Response {
	if err := cr.SignIn(sc.ID()); err != nil {
		return NewResponseErr(ErrorGeneric, err.Error())
	}
	return NewResponseSucc(nil)
}

//SignInPeriod 周期卡 签到
func (ch *Character) SignInPeriod(sc datatypes.SICharacter, cr *repositories.CharacterRepo) *Response {
	if err := cr.SignInPeriod(sc.ID()); err != nil {
		return NewResponseErr(ErrorGeneric, err.Error())
	}
	return NewResponseSucc(nil)
}

//CHPeriodBM 购买 时间卡参数
type CHPeriodBM struct {
	PeriodType models.CharacterPeriodType
}

//BuyPeriod 购买时间卡
func (ch *Character) BuyPeriod(sc datatypes.SICharacter, bm *CHPeriodBM, cr *repositories.CharacterRepo) *Response {
	if bm.PeriodType < models.CharacterNormal && bm.PeriodType > models.CharacterMonthly {
		return NewResponseErr(ErrorArgument, "不支持的时间卡")
	}
	if err := cr.BuyPeriod(sc.ID(), bm.PeriodType); err != nil {
		return NewResponseErr(ErrorGeneric, err.Error())
	}
	return NewResponseSucc(nil)
}

//CHDepositBM 人物充值
type CHDepositBM struct {
	Lot int64
}

//Deposit 充值
func (ch *Character) Deposit(sc datatypes.SICharacter, bm *CHDepositBM, cr *repositories.CharacterRepo) *Response {
	if bm.Lot <= 0 {
		return NewResponseErr(ErrorArgument, "非法数量")
	}
	if err := cr.Deposit(sc.ID(), bm.Lot); err != nil {
		return NewResponseErr(ErrorGeneric, err.Error())
	}

	return NewResponseSucc(nil)
}
